home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / UUCICO / DCPXFER.C < prev    next >
C/C++ Source or Header  |  1992-11-30  |  47KB  |  1,267 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    d c p x f e r . c                                               */
  3. /*                                                                    */
  4. /*    Procotol independent transfer level for UUCICO                  */
  5. /*                                                                    */
  6. /*    Stuart Lynne May/87                                             */
  7. /*                                                                    */
  8. /*    Copyright (c) Richard H. Lamb 1985, 1986, 1987                  */
  9. /*    Changes Copyright (c) Stuart Lynne 1987                         */
  10. /*    Changes Copyright (c) Andrew H. Derbyshire 1989                 */
  11. /*    Changes Copyright (c) Jordan Brown 1990, 1991                   */
  12. /*    Changes Copyright (c) Kendra Electronic Wonderworks 1990-1992   */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*
  16.  *       $Id: DCPXFER.C 1.10 1992/12/01 04:37:03 ahd Exp $
  17.  *
  18.  *       $Log: DCPXFER.C $
  19.  * Revision 1.10  1992/12/01  04:37:03  ahd
  20.  * Suppress routine names transfered from debug level 0 and 1
  21.  *
  22.  * Revision 1.9  1992/11/29  22:09:10  ahd
  23.  * Change size_t to int to suppress warning message
  24.  *
  25.  * Revision 1.8  1992/11/28  19:51:16  ahd
  26.  * If in multitask mode, only open syslog on demand basis
  27.  *
  28.  * Revision 1.7  1992/11/22  21:20:45  ahd
  29.  * Make databuf char rather than unsigned char
  30.  *
  31.  * Revision 1.6  1992/11/20  12:39:10  ahd
  32.  * Add instead of substracting on the receive buffer!
  33.  *
  34.  * Revision 1.5  1992/11/19  03:01:31  ahd
  35.  * drop rcsid
  36.  *
  37.  * Revision 1.4  1992/11/19  02:36:12  ahd
  38.  * Insure log file is flushed
  39.  *
  40.  * Revision 1.3  1992/11/17  13:44:24  ahd
  41.  * Drop command[BUFSIZ], using databuf instead.
  42.  *
  43.  * Revision 1.2  1992/11/15  20:09:50  ahd
  44.  * Use unbuffered files to eliminate extra data copy
  45.  * Clean up modem file support for different protocols
  46.  *
  47.  */
  48.  
  49.  /*
  50.    Additional maintenance Notes:
  51.  
  52.    01Nov87 - that strncpy should be a memcpy! - Jal
  53.    22Jul90 - Add check for existence of the file before writing
  54.              it.                                                  ahd
  55.    09Apr91 - Add numerous changes from H.A.E.Broomhall and Cliff
  56.              Stanford for bidirectional support                   ahd
  57.    05Jul91 - Merged various changes from Jordan Brown's (HJB)
  58.              version of UUPC/extended to clean up transmission
  59.              of commands, etc.                                    ahd
  60.    09Jul91 - Rewrite to use unique routines for all four kinds of
  61.              transfers to allow for testing and security          ahd
  62.  */
  63.  
  64.  
  65. /*--------------------------------------------------------------------*/
  66. /*                        System include files                        */
  67. /*--------------------------------------------------------------------*/
  68.  
  69. #include <ctype.h>
  70. #include <fcntl.h>
  71. #include <direct.h>
  72. #include <io.h>
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <string.h>
  76. #include <time.h>
  77. #include <sys/types.h>
  78. #include <sys/stat.h>
  79. #include <sys/timeb.h>
  80.  
  81. /*--------------------------------------------------------------------*/
  82. /*                    UUPC/extended include files                     */
  83. /*--------------------------------------------------------------------*/
  84.  
  85. #include "lib.h"
  86. #include "dcp.h"
  87. #include "dcpsys.h"
  88. #include "dcpxfer.h"
  89. #include "expath.h"
  90. #include "hlib.h"
  91. #include "hostable.h"
  92. #include "import.h"
  93. #include "security.h"
  94. #include "modem.h"
  95. #include "ulib.h"
  96.  
  97. /*--------------------------------------------------------------------*/
  98. /*                          Global variables                          */
  99. /*--------------------------------------------------------------------*/
  100.  
  101. static char *databuf = NULL;
  102. static unsigned int xfer_bufsize = 0;
  103.  
  104. static char fname[FILENAME_MAX], tname[FILENAME_MAX], dname[FILENAME_MAX];
  105. static char type, cmdopts[16];
  106.  
  107. static long bytes;
  108. static struct timeb start_time;
  109.  
  110. static boolean spool = FALSE; /* Received file is into spool dir     */
  111. static char spolname[FILENAME_MAX];
  112.                               /* Final host name of file to be
  113.                                  received into spool directory       */
  114. static char tempname[FILENAME_MAX];
  115.                               /* Temp name used to create received
  116.                                  file                                */
  117.  
  118. currentfile();
  119.  
  120. /*--------------------------------------------------------------------*/
  121. /*                    Internal function prototypes                    */
  122. /*--------------------------------------------------------------------*/
  123.  
  124. static boolean pktgetstr( char *s);
  125. static boolean pktsendstr( char *s );
  126. static void buf_init( void );
  127.  
  128. static int  bufill(char  *buffer);
  129. static int  bufwrite(char  *buffer,int  len);
  130.  
  131. /*************** SEND PROTOCOL ***************************/
  132.  
  133. /*--------------------------------------------------------------------*/
  134. /*    s d a t a                                                       */
  135. /*                                                                    */
  136. /*    Send File Data                                                  */
  137. /*--------------------------------------------------------------------*/
  138.  
  139. XFER_STATE sdata( void )
  140. {
  141.    int S_size;
  142.    int used = 0;
  143.  
  144.    S_size = bufill((char *) databuf);
  145.  
  146.    if (S_size == 0)                 /* Get data from file         */
  147.       return XFER_SENDEOF;          /* if EOF set state to that   */
  148.    else if (S_size == -1)           /* If error ...               */
  149.       return XFER_ABORT;            /* Toss file                  */
  150.  
  151.    do {
  152.       size_t xmit = min( (size_t) S_size - used , pktsize );
  153.  
  154.       if ((*sendpkt)((char *) databuf + used, xmit) != OK)   /* Send data */
  155.       {
  156.          fclose( xfer_stream );
  157.          xfer_stream = NULL;
  158.          return XFER_LOST;    /* Trouble!                            */
  159.       }
  160.       else
  161.          used += xmit;
  162.  
  163.    } while( S_size > used );
  164.  
  165.    return XFER_SENDDATA;   /* Remain in send state                */
  166.  
  167. } /*sdata*/
  168.  
  169.  
  170. /*--------------------------------------------------------------------*/
  171. /*    b u f i l l                                                     */
  172. /*                                                                    */
  173. /*    Get a bufferful of data from the file that's being sent.        */
  174. /*    (Should perform input buffering here, perhaps 4K at a time.)    */
  175. /*--------------------------------------------------------------------*/
  176.  
  177. static int bufill(char *buffer)
  178. {
  179.    size_t count = fread(buffer,
  180.                         sizeof *buffer,
  181.                         xfer_bufsize,
  182.                         xfer_stream);
  183.  
  184.    bytes += count;
  185.    if ((count < xfer_bufsize) && ferror(xfer_stream))
  186.    {
  187.       printerr("bufill");
  188.       clearerr(xfer_stream);
  189.       return -1;
  190.    }
  191.    return count;
  192.  
  193. } /*bufill*/
  194.  
  195. /*--------------------------------------------------------------------*/
  196. /*    b u f w r i t e                                                 */
  197. /*                                                                    */
  198. /*    Write a bufferful of data to the file that's being received.    */
  199. /*--------------------------------------------------------------------*/
  200.  
  201. static int bufwrite(char *buffer, int len)
  202. {
  203.    int count = fwrite(buffer, sizeof *buffer, len, xfer_stream);
  204.  
  205.    bytes += count;
  206.    if (count < len)
  207.    {
  208.       printerr("bufwrite");
  209.       clearerr(xfer_stream);
  210.    }
  211.  
  212.    return count;
  213.  
  214. } /*bufwrite*/
  215.  
  216. /*--------------------------------------------------------------------*/
  217. /*    s b r e a k                                                     */
  218. /*                                                                    */
  219. /*    Switch from master to slave mode                                */
  220. /*                                                                    */
  221. /*    Sequence:                                                       */
  222. /*                                                                    */
  223. /*       We send "H" to other host to ask if we should hang up        */
  224. /*       If it responds "HN", it has work for us, we become           */
  225. /*          the slave.                                                */
  226. /*       If it responds "HY", it has no work for us, we               */
  227. /*          response "HY" (we have no work either), and               */
  228. /*          terminate protocol and hangup                             */
  229. /*                                                                    */
  230. /*    Note that if more work is queued on the local system while      */
  231. /*    we are in slave mode, schkdir() causes us to become the         */
  232. /*    master again; we just decline here to avoid trying the queue    */
  233. /*    again without intervening work from the other side.             */
  234. /*--------------------------------------------------------------------*/
  235.  
  236. XFER_STATE sbreak( void )
  237. {
  238.    if (!pktsendstr("H"))      /* Tell slave it can become the master */
  239.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  240.  
  241.    if (!pktgetstr((char *)databuf)) /* Get their response            */
  242.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  243.  
  244.    if ((*databuf != 'H') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  245.    {
  246.       printmsg(0,"Invalid response from remote: %s",databuf);
  247.       return XFER_ABORT;
  248.    }
  249.  
  250.    if (databuf[1] == 'N')     /* "HN" (have work) message from host? */
  251.    {                          /* Yes --> Enter Receive mode          */
  252.       printmsg( 2, "sbreak: Switch into slave mode" );
  253.       return XFER_SLAVE;
  254.    }
  255.    else {                     /* No --> Remote host is done as well  */
  256.       pktsendstr("HY");       /* Tell the host we are done as well   */
  257.       hostp->hstatus = called;/* Update host status flags            */
  258.       return XFER_ENDP;       /* Terminate the protocol              */
  259.    } /* else */
  260.  
  261. } /*sbreak*/
  262.  
  263. /*--------------------------------------------------------------------*/
  264. /*    s e o f                                                         */
  265. /*                                                                    */
  266. /*    Send End-Of-File                                                */
  267. /*--------------------------------------------------------------------*/
  268.  
  269. XFER_STATE seof( const boolean purge_file )
  270. {
  271.  
  272.    struct tm  *tmx;
  273.    long ticks;
  274.    struct timeb now;
  275.    char hostname[FILENAME_MAX];
  276.  
  277. /*--------------------------------------------------------------------*/
  278. /*    Send end-of-file indication, and perhaps receive a              */
  279. /*    lower-layer ACK/NAK                                             */
  280. /*--------------------------------------------------------------------*/
  281.  
  282.    switch ((*eofpkt)())
  283.    {
  284.       case RETRY:                /* retry */
  285.          printmsg(0, "Remote system asks that the file be resent");
  286.          fseek(xfer_stream, 0L, SEEK_SET);
  287.          bytes = 0;
  288.          (*filepkt)();           /* warmstart file-transfer protocol */
  289.          return XFER_SENDDATA;   /* stay in data phase */
  290.  
  291.       case FAILED:
  292.          fclose(xfer_stream);
  293.          xfer_stream = NULL;
  294.          return XFER_ABORT;      /* cannot send file */
  295.  
  296.       case OK:
  297.          fclose(xfer_stream);
  298.          xfer_stream = NULL;
  299.          break;                  /* sent, proceed */
  300.  
  301.       default:
  302.          fclose(xfer_stream);
  303.          xfer_stream = NULL;
  304.          return XFER_LOST;
  305.    }
  306.  
  307.    if (!pktgetstr((char *)databuf)) /* Receive CY or CN              */
  308.       return XFER_LOST;       /* Bomb the connection if no packet    */
  309.  
  310.    if ((*databuf != 'C') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  311.    {
  312.       printmsg(0,"Invalid response from remote: %s",
  313.                   ( char *) databuf);
  314.       return XFER_ABORT;
  315.    }
  316.  
  317.    if (!equaln((char *) databuf, "CY", 2))
  318.       printmsg(0,"seof: Host was unable to save file after transmission");
  319.  
  320. /*--------------------------------------------------------------------*/
  321. /*                   If local spool file, delete it                   */
  322. /*--------------------------------------------------------------------*/
  323.  
  324.    importpath(hostname, dname, rmtname);
  325.                               /* Local name also used by logging     */
  326.  
  327.    if (purge_file && !equal(dname,"D.0"))
  328.    {
  329.      unlink( hostname );
  330.      printmsg(4,"seof: Deleted file %s (%s)", dname, hostname );
  331.    } /* if (purge_file && !equal(dname,"D.0")) */
  332.  
  333. /*--------------------------------------------------------------------*/
  334. /*                            Update stats                            */
  335. /*--------------------------------------------------------------------*/
  336.  
  337.    remote_stats.fsent++;
  338.    remote_stats.bsent += bytes;
  339.  
  340.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  341.    {
  342.       ftime(&now);
  343.       ticks = (now.time - start_time.time) * 1000 +
  344.                ((long) now.millitm - (long) start_time.millitm);
  345.       printmsg(2, "Transfer completed, %ld chars/sec",
  346.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  347.  
  348.       if (bflag[F_SYSLOG])
  349.       {
  350.          tmx = localtime(&now.time);
  351.          if ( bflag[F_MULTITASK] )
  352.             syslog = FOPEN(SYSLOG, "a", TEXT);
  353.  
  354.          if (( syslog == NULL ) || setvbuf( syslog, NULL, _IONBF, 0))
  355.             printerr(SYSLOG);
  356.          else {
  357.             fprintf( syslog,
  358.                "%s!%s (%s) (%d/%d-%02d:%02d:%02d) -> %ld / %ld.%02d secs\n",
  359.                    E_nodename, tname, hostname,
  360.                    (tmx->tm_mon+1), tmx->tm_mday,
  361.                    tmx->tm_hour, tmx->tm_min, tmx->tm_sec, bytes,
  362.                    ticks / 1000 , (int) ((ticks % 1000) / 10) );
  363.             fclose( syslog );
  364.             syslog = NULL;
  365.          }
  366.  
  367.       } /* if (bflag[F_SYSLOG] ) */
  368.  
  369.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  370.  
  371. /*--------------------------------------------------------------------*/
  372. /*                          Return to caller                          */
  373. /*--------------------------------------------------------------------*/
  374.  
  375.    return XFER_FILEDONE;    /* go get the next file to send */
  376.  
  377. } /*seof*/
  378.  
  379. /*--------------------------------------------------------------------*/
  380. /*    n e w r e q u e s t                                             */
  381. /*                                                                    */
  382. /*    Determine the next request to be sent to other host             */
  383. /*--------------------------------------------------------------------*/
  384.  
  385. XFER_STATE newrequest( void )
  386. {
  387.    int i;
  388.  
  389. /*--------------------------------------------------------------------*/
  390. /*                 Verify we have no work in progress                 */
  391. /*--------------------------------------------------------------------*/
  392.  
  393.    if (!(xfer_stream == NULL))
  394.       return XFER_ABORT;      /* Something is already being
  395.                                  transferred; we're in trouble!      */
  396.  
  397. /*--------------------------------------------------------------------*/
  398. /*    Look for work in the current call file; if we do not find       */
  399. /*    any, the job is complete and we can delete all the files we     */
  400. /*    worked on in the file                                           */
  401. /*--------------------------------------------------------------------*/
  402.  
  403.    if (fgets(databuf, xfer_bufsize, fwork) == nil(char)) /* More data?     */
  404.    {                          /* No --> clean up list of files       */
  405.       printmsg(3, "newrequest: EOF for workfile %s",workfile);
  406.       fclose(fwork);
  407.       fwork = nil(FILE);
  408.       unlink(workfile);       /* Delete completed call file          */
  409.       return XFER_NEXTJOB;    /* Get next C.* file to process     */
  410.    } /* if (fgets(databuf, xfer_bufsize, fwork) == nil(char)) */
  411.  
  412. /*--------------------------------------------------------------------*/
  413. /*                  We have a new request to process                  */
  414. /*--------------------------------------------------------------------*/
  415.  
  416.    i = strlen(databuf) - 1;
  417.    printmsg(3, "newrequest: got command from %s",workfile);
  418.    if (databuf[i] == '\n')            /* remove new_line from card */
  419.       databuf[i] = '\0';
  420.  
  421.    sscanf(databuf, "%c %s %s %*s %s %s",
  422.          &type, fname, tname, cmdopts, dname);
  423.  
  424. /*--------------------------------------------------------------------*/
  425. /*                           Reset counters                           */
  426. /*--------------------------------------------------------------------*/
  427.  
  428.    bytes = 0;
  429.    ftime(&start_time);
  430.    (*filepkt)();              /* Init for file transfer */
  431.  
  432. /*--------------------------------------------------------------------*/
  433. /*             Process the command according to its type              */
  434. /*--------------------------------------------------------------------*/
  435.  
  436.    switch( type )
  437.    {
  438.       case 'R':
  439.          return XFER_GETFILE;
  440.  
  441.       case 'S':
  442.          return XFER_PUTFILE;
  443.  
  444.       default:
  445.          return XFER_FILEDONE;   /* Ignore the line                  */
  446.    } /* switch */
  447.  
  448. } /* newrequest */
  449.  
  450. /*--------------------------------------------------------------------*/
  451. /*    s s f i l e                                                     */
  452. /*                                                                    */
  453. /*    Send File Header for file to be sent                            */
  454. /*--------------------------------------------------------------------*/
  455.  
  456. XFER_STATE ssfile( void )
  457. {
  458.    char hostfile[FILENAME_MAX];
  459.    char *filename;
  460.  
  461.    if (equal(dname, "D.0"))   /* Is there a spool file?              */
  462.       filename = fname;       /* No --> Use the real name            */
  463.    else
  464.       filename = dname;       /* Yes --> Use it                      */
  465.  
  466. /*--------------------------------------------------------------------*/
  467. /*              Convert the file name to our local name               */
  468. /*--------------------------------------------------------------------*/
  469.  
  470.    importpath(hostfile, filename, rmtname);
  471.  
  472. /*--------------------------------------------------------------------*/
  473. /*    Try to open the file; if we fail, we just continue, because we  */
  474. /*    may have sent the file on a previous call which failed part     */
  475. /*    way through this job                                            */
  476. /*--------------------------------------------------------------------*/
  477.  
  478.    xfer_stream = FOPEN( hostfile, "r", BINARY );
  479.                                     /* Open stream to send           */
  480.    if (xfer_stream == NULL)
  481.    {
  482.       printmsg(0, "ssfile: Cannot open file %s (%s).", filename, hostfile);
  483.       printerr(hostfile);
  484.       return XFER_FILEDONE;      /* Try next file in this job  */
  485.    } /* if */
  486.  
  487. /*--------------------------------------------------------------------*/
  488. /*              The file is open, now set its buffering               */
  489. /*--------------------------------------------------------------------*/
  490.  
  491.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  492.    {
  493.       printmsg(0, "ssfile: Cannot unbuffer file %s (%s).",
  494.                   filename, hostfile);
  495.       printerr(hostfile);
  496.       fclose(xfer_stream);
  497.       xfer_stream = NULL;
  498.       return XFER_ABORT;         /* Clearly not our day; quit  */
  499.    } /* if */
  500.  
  501. /*--------------------------------------------------------------------*/
  502. /*    Okay, we have a file to process; offer it to the other host     */
  503. /*--------------------------------------------------------------------*/
  504.  
  505.    printmsg( equal(fname,dname) ? 2 : 0,
  506.             "Sending \"%s\" (%s) as \"%s\"", fname, hostfile, tname);
  507.    if (!pktsendstr( databuf ))   /* Tell them what is coming at them */
  508.    {
  509.       fclose(xfer_stream);
  510.       xfer_stream = NULL;
  511.       return XFER_LOST;
  512.    }
  513.  
  514.    if (!pktgetstr((char *)databuf))
  515.    {
  516.       fclose(xfer_stream);
  517.       xfer_stream = NULL;
  518.       return XFER_LOST;
  519.    }
  520.  
  521.    if ((*databuf != 'S') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  522.    {
  523.       printmsg(0,"Invalid response from remote: %s",databuf);
  524.       fclose(xfer_stream);
  525.       xfer_stream = NULL;
  526.       return XFER_ABORT;
  527.    }
  528.  
  529.    if (databuf[1] != 'Y')     /* Otherwise reject file transfer?     */
  530.    {                          /* Yes --> Look for next file          */
  531.       printmsg(0, "ssfile: Remote host rejected file %s, reason %s",
  532.                    tname,
  533.                    databuf[2] ? (char *) &databuf[2] : "unknown" );
  534.       fclose( xfer_stream );
  535.       xfer_stream = NULL;
  536.       return XFER_FILEDONE;
  537.    }
  538.  
  539.    return XFER_SENDDATA;      /* Enter data transmission mode        */
  540.  
  541. } /*ssfile*/
  542.  
  543. /*--------------------------------------------------------------------*/
  544. /*    s r f i l e                                                     */
  545. /*                                                                    */
  546. /*    Send File Header for file to be received                        */
  547. /*--------------------------------------------------------------------*/
  548.  
  549. XFER_STATE srfile( void )
  550. {
  551.    char hostfile[FILENAME_MAX];
  552.    struct  stat    statbuf;
  553.  
  554. /*--------------------------------------------------------------------*/
  555. /*               Convert the filename to our local name               */
  556. /*--------------------------------------------------------------------*/
  557.  
  558.    importpath(hostfile, tname, rmtname);
  559.  
  560. /*--------------------------------------------------------------------*/
  561. /*    If the destination is a directory, put the originating          */
  562. /*    original file name at the end of the path                       */
  563. /*--------------------------------------------------------------------*/
  564.  
  565.    if ((hostfile[strlen(hostfile) - 1] == '/') ||
  566.        ((stat(hostfile , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  567.    {
  568.       char *slash = strrchr( fname, '/');
  569.  
  570.       if ( slash == NULL )
  571.          slash = fname;
  572.       else
  573.          slash ++ ;
  574.  
  575.       printmsg(3, "srfile: Destination \"%s\" is directory, \
  576. appending filename \"%s\"", hostfile, slash);
  577.  
  578.       if (hostfile[strlen(hostfile) - 1] != '/')
  579.          strcat(hostfile, "/");
  580.  
  581.       strcat( hostfile, slash );
  582.    } /* if */
  583.  
  584.    printmsg(0, "Receiving \"%s\" as \"%s\" (%s)", fname, tname, hostfile);
  585.  
  586.    if (!pktsendstr( databuf ))
  587.       return XFER_LOST;
  588.  
  589.    if (!pktgetstr((char *)databuf))
  590.       return XFER_LOST;
  591.  
  592.    if ((*databuf != 'R') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  593.    {
  594.       printmsg(0,"Invalid response from remote: %s",
  595.                   databuf);
  596.       return XFER_ABORT;
  597.    }
  598.  
  599.    if (databuf[1] != 'Y')     /* Otherwise reject file transfer?     */
  600.    {                          /* Yes --> Look for next file          */
  601.       printmsg(0, "srfile: Remote host denied access to file %s, reason %s",
  602.          fname, databuf[2] ? (char *) &databuf[2] : "unknown" );
  603.       return XFER_FILEDONE;
  604.    }
  605.  
  606. /*--------------------------------------------------------------------*/
  607. /*    We should verify the directory exists if the user doesn't       */
  608. /*    specify the -d option, but I've got enough problems this        */
  609. /*    week; we'll just auto-create using FOPEN()                      */
  610. /*--------------------------------------------------------------------*/
  611.  
  612.    xfer_stream = FOPEN(hostfile, "w", BINARY);
  613.                            /* Allow auto-create of directory      */
  614.    if (xfer_stream == NULL)
  615.    {
  616.       printmsg(0, "srfile: cannot create %s", hostfile);
  617.       printerr(hostfile);
  618.       return XFER_ABORT;
  619.    }
  620.  
  621. /*--------------------------------------------------------------------*/
  622. /*                     Set buffering for the file                     */
  623. /*--------------------------------------------------------------------*/
  624.  
  625.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  626.    {
  627.       printmsg(0, "srfile: Cannot unbuffer file %s (%s).",
  628.           tname, hostfile);
  629.       printerr(hostfile);
  630.       fclose(xfer_stream);
  631.       xfer_stream = NULL;
  632.       return XFER_ABORT;
  633.    } /* if */
  634.  
  635.    spool = FALSE;             /* Do not rename file at completion */
  636.    return XFER_RECVDATA;      /* Now start receiving the data     */
  637.  
  638. } /*stfile*/
  639.  
  640. /*--------------------------------------------------------------------*/
  641. /*    s i n i t                                                       */
  642. /*                                                                    */
  643. /*    Send Initiate:  send this host's parameters and get other       */
  644. /*    side's back.                                                    */
  645. /*--------------------------------------------------------------------*/
  646.  
  647. XFER_STATE sinit( void )
  648. {
  649.    if ((*openpk)( TRUE ))     /* Initialize in caller mode           */
  650.       return XFER_ABORT;
  651.    else {
  652.       buf_init();
  653.       return XFER_MASTER;
  654.    } /* else */
  655.  
  656. } /*sinit*/
  657.  
  658.  
  659. /*********************** MISC SUB SUB PROTOCOL *************************/
  660.  
  661. /*
  662.    s c h k d i r
  663.  
  664.    scan spooling directory for C.* files for the other system
  665. */
  666.  
  667. XFER_STATE schkdir( const boolean outbound, const char callgrade )
  668. {
  669.    XFER_STATE c;
  670.  
  671.    if ( hostp->hsecure->sendfiles || outbound )
  672.                                  /* Send our work to other host?        */
  673.    {
  674.       c = scandir(rmtname,callgrade);
  675.                                  /* Determine if data for the host      */
  676.       scandir( NULL,callgrade ); /* Reset directory search pointers     */
  677.    }
  678.    else {
  679.       hostp->hstatus = called;/* Update host status flags            */
  680.       c = XFER_NOLOCAL;       /* Do not send data on inbound call    */
  681.    }
  682.  
  683.    switch ( c )
  684.    {
  685.       case XFER_ABORT:        /* Internal error opening file         */
  686.          return XFER_ABORT;
  687.  
  688.       case XFER_NOLOCAL:      /* No work for host                    */
  689.          if (! pktsendstr("HY") )
  690.             return XFER_LOST;
  691.  
  692.          if (!pktgetstr((char *)databuf))
  693.             return XFER_LOST; /* Didn't get response, die quietly    */
  694.          else {
  695.             hostp->hstatus = called;/* Update host status flags            */
  696.             return XFER_ENDP; /* Got response, we're out of here     */
  697.          }
  698.  
  699.       case XFER_REQUEST:
  700.          if (! pktsendstr("HN") )
  701.             return XFER_LOST;
  702.          else {
  703.             printmsg( 2, "schkdir: Switch into master mode" );
  704.             return XFER_MASTER;
  705.          }
  706.  
  707.       default:
  708.          panic();
  709.          return XFER_ABORT;
  710.  
  711.    } /* switch */
  712. } /*schkdir*/
  713.  
  714. /*--------------------------------------------------------------------*/
  715. /*    e n d p                                                         */
  716. /*                                                                    */
  717. /*    end the protocol                                                */
  718. /*--------------------------------------------------------------------*/
  719.  
  720. XFER_STATE endp( void )
  721. {
  722.    (*closepk)();
  723.  
  724.    if (spool)
  725.    {
  726.       unlink(tempname);
  727.       spool = FALSE;
  728.    }
  729.    return XFER_EXIT;
  730.  
  731. } /*endp*/
  732.  
  733.  
  734. /*********************** RECIEVE PROTOCOL **********************/
  735.  
  736. /*--------------------------------------------------------------------*/
  737. /*    r i n i t                                                       */
  738. /*                                                                    */
  739. /*    Receive Initialization                                          */
  740. /*--------------------------------------------------------------------*/
  741.  
  742. XFER_STATE rinit( void )
  743. {
  744.  
  745.    if ((*openpk)( FALSE ) == OK )   /* Initialize in callee mode     */
  746.    {
  747.       buf_init();
  748.       return XFER_SLAVE;
  749.    }
  750.    else
  751.       return XFER_LOST;
  752.  
  753. } /*rinit*/
  754.  
  755. /*--------------------------------------------------------------------*/
  756. /*    r h e a d e r                                                   */
  757. /*                                                                    */
  758. /*    Receive File Header                                             */
  759. /*--------------------------------------------------------------------*/
  760.  
  761. XFER_STATE rheader( void )
  762. {
  763.  
  764.    if (!pktgetstr(databuf))
  765.       return XFER_LOST;
  766.  
  767. /*--------------------------------------------------------------------*/
  768. /*        Return if the remote system has no more data for us         */
  769. /*--------------------------------------------------------------------*/
  770.  
  771.    if ((databuf[0] & 0x7f) == 'H')
  772.       return XFER_NOREMOTE;   /* Report master has no more data to   */
  773.  
  774. /*--------------------------------------------------------------------*/
  775. /*                  Begin transforming the file name                  */
  776. /*--------------------------------------------------------------------*/
  777.  
  778.    sscanf(databuf, "%c %s %s %*s %s %s",
  779.          &type, fname, tname, cmdopts, dname);
  780.  
  781. /*--------------------------------------------------------------------*/
  782. /*                           Reset counters                           */
  783. /*--------------------------------------------------------------------*/
  784.  
  785.    ftime(&start_time);
  786.    bytes = 0;
  787.    (*filepkt)();              /* Init for file transfer */
  788.  
  789. /*--------------------------------------------------------------------*/
  790. /*                 Return with next state to process                  */
  791. /*--------------------------------------------------------------------*/
  792.  
  793.    switch (type)
  794.    {
  795.       case 'R':
  796.          return XFER_GIVEFILE;
  797.  
  798.       case 'S':
  799.          return XFER_TAKEFILE;
  800.  
  801.       default:
  802.          printmsg(0,"rheader: Unsupported verb \"%c\" rejected",type);
  803.          if (!pktsendstr("XN"))  /* Reject the request               */
  804.             return XFER_LOST;    /* Die if reponse fails             */
  805.          else
  806.             return XFER_FILEDONE;   /* Process next request          */
  807.    } /* switch */
  808.  
  809. } /* rheader */
  810.  
  811. /*--------------------------------------------------------------------*/
  812. /*    r r f i l e                                                     */
  813. /*                                                                    */
  814. /*    Setup for receiving a file as requested by the remote host      */
  815. /*--------------------------------------------------------------------*/
  816.  
  817. XFER_STATE rrfile( void )
  818. {
  819.    char filename[FILENAME_MAX];
  820.    size_t subscript;
  821.    struct  stat    statbuf;
  822.  
  823. /*--------------------------------------------------------------------*/
  824. /*       Determine if the file can go into the spool directory        */
  825. /*--------------------------------------------------------------------*/
  826.  
  827.    spool = ((*tname == 'D') || (*tname == 'X')) && tname[1] == '.';
  828.  
  829.    expand_path( strcpy( filename, tname),
  830.       spool ? "." : securep->pubdir, securep->pubdir , NULL );
  831.  
  832. /*--------------------------------------------------------------------*/
  833. /*       Check if the name is a directory name (end with a '/')       */
  834. /*--------------------------------------------------------------------*/
  835.  
  836.    subscript = strlen( filename ) - 1;
  837.  
  838.    if ((filename[subscript] == '/') ||
  839.        ((stat(filename , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  840.    {
  841.       char *slash = strrchr(fname, '/');
  842.       if (slash  == NULL)
  843.          slash = fname;
  844.       else
  845.          slash++;
  846.  
  847.       printmsg(3, "rrfile: destination is directory \"%s\", adding \"%s\"",
  848.                filename, slash);
  849.  
  850.       if ( filename[ subscript ] != '/')
  851.          strcat(filename, "/");
  852.       strcat(filename, slash);
  853.    } /* if */
  854.  
  855. /*--------------------------------------------------------------------*/
  856. /*          Let host munge filename as appropriate                    */
  857. /*--------------------------------------------------------------------*/
  858.  
  859.    importpath(spolname, filename, rmtname);
  860.  
  861. /*--------------------------------------------------------------------*/
  862. /* If the name has a path and we don't allow it, reject the transfer  */
  863. /*--------------------------------------------------------------------*/
  864.  
  865.    if ( !spool && !ValidateFile( spolname , ALLOW_WRITE ))
  866.    {
  867.       if (!pktsendstr("SN2")) /* Report access denied to requestor   */
  868.          return XFER_LOST;
  869.       else
  870.          return XFER_FILEDONE;   /* Look for next file from master   */
  871.    } /* if */
  872.  
  873. /*--------------------------------------------------------------------*/
  874. /*            The filename is transformed, try to open it             */
  875. /*--------------------------------------------------------------------*/
  876.  
  877.    if (spool)
  878. #ifdef __TURBOC__
  879.       xfer_stream = fopen( tmpnam( tempname ), "wb");
  880. #else
  881.  
  882. /*--------------------------------------------------------------------*/
  883. /*    MS C 6.0 doesn't generate the name for the current directory,   */
  884. /*    so we cheat and use our own temporary file name generation      */
  885. /*    routine.                                                        */
  886. /*--------------------------------------------------------------------*/
  887.  
  888.    {
  889.       char *savetemp = E_tempdir;   /* Save the real temp directory  */
  890.  
  891.       E_tempdir = E_spooldir;       /* Generate this file in spool   */
  892.       mktempname(tempname, "TMP");  /* Get the file name             */
  893.       E_tempdir = savetemp;         /* Restore true directory name   */
  894.  
  895.       xfer_stream = fopen( tempname , "wb");
  896.  
  897.    }
  898. #endif
  899.  
  900.    else if (strchr( cmdopts,'d'))
  901.       xfer_stream = FOPEN( spolname, "w", BINARY );
  902.    else
  903.       xfer_stream = fopen( spolname, "wb");
  904.  
  905.  
  906.    if (xfer_stream == NULL)
  907.    {
  908.       printmsg(0, "rrfile: cannot open file %s (%s).",
  909.            filename, spool ? tempname : spolname);
  910.       printerr(spool ? tempname : spolname);
  911.       if (!pktsendstr("SN4"))    /* Report cannot create file     */
  912.          return XFER_LOST;       /* School is out, die            */
  913.       else
  914.          return XFER_FILEDONE;   /* Tell them to send next file   */
  915.    } /* if */
  916.  
  917. /*--------------------------------------------------------------------*/
  918. /*               The file is open, now try to buffer it               */
  919. /*--------------------------------------------------------------------*/
  920.  
  921.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  922.    {
  923.       printmsg(0, "rrfile: Cannot unbuffer file %s (%s).",
  924.           filename, spool ? tempname : spolname);
  925.       printerr(spool ? tempname : spolname);
  926.       fclose(xfer_stream);
  927.       xfer_stream = NULL;
  928.       pktsendstr("SN4");             /* Report cannot create file     */
  929.       return XFER_ABORT;
  930.    } /* if */
  931.  
  932. /*--------------------------------------------------------------------*/
  933. /*    Announce we are receiving the file to console and to remote     */
  934. /*--------------------------------------------------------------------*/
  935.  
  936.    printmsg(spool ? 2 : 0 , "Receiving \"%s\" as \"%s\" (%s)",
  937.                fname,filename,spolname);
  938.  
  939.    if (spool)
  940.       printmsg(2,"Using temp name %s",tempname);
  941.  
  942.    if (!pktsendstr("SY"))
  943.    {
  944.       fclose(xfer_stream);
  945.       xfer_stream = NULL;
  946.       return XFER_LOST;
  947.    }
  948.  
  949.    return XFER_RECVDATA;   /* Switch to data state                */
  950.  
  951. } /*rrfile*/
  952.  
  953. /*--------------------------------------------------------------------*/
  954. /*    r s f i l e                                                     */
  955. /*                                                                    */
  956. /*    Receive File Header for a file remote has requested us to       */
  957. /*    send                                                            */
  958. /*--------------------------------------------------------------------*/
  959.  
  960. XFER_STATE rsfile( void )
  961. {
  962.    char filename[FILENAME_MAX];
  963.    char hostname[FILENAME_MAX];
  964.    struct  stat    statbuf;
  965.    size_t subscript;
  966.  
  967.    expand_path( strcpy(filename, fname ) ,
  968.                 securep->pubdir ,
  969.                 securep->pubdir ,
  970.                 NULL );
  971.  
  972. /*--------------------------------------------------------------------*/
  973. /*               Let host munge filename as appropriate               */
  974. /*--------------------------------------------------------------------*/
  975.  
  976.    importpath(hostname, filename, rmtname);
  977.    printmsg(3, "rsfile: input \"%s\", source \"%s\", host \"%s\"",
  978.                                     fname, filename , hostname);
  979.  
  980. /*--------------------------------------------------------------------*/
  981. /*       Check if the name is a directory name (end with a '/')       */
  982. /*--------------------------------------------------------------------*/
  983.  
  984.    subscript = strlen( filename ) - 1;
  985.  
  986.    if ((filename[subscript] == '/') ||
  987.        ((stat(hostname , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  988.    {
  989.       printmsg(3, "rsfile: source is directory \"%s\", rejecting",
  990.                hostname);
  991.  
  992.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  993.          return XFER_LOST;       /* School is out, die            */
  994.       else
  995.          return XFER_FILEDONE;   /* Tell them to send next file   */
  996.    } /* if */
  997.  
  998. /*--------------------------------------------------------------------*/
  999. /*                Check the access to the file desired                */
  1000. /*--------------------------------------------------------------------*/
  1001.  
  1002.    if ( !ValidateFile( hostname , ALLOW_READ ))
  1003.    {
  1004.       if (!pktsendstr("RN2")) /* Report access denied to requestor   */
  1005.          return XFER_LOST;
  1006.       else
  1007.          return XFER_FILEDONE;   /* Look for next file from master   */
  1008.    } /* if */
  1009.  
  1010. /*--------------------------------------------------------------------*/
  1011. /*            The filename is transformed, try to open it             */
  1012. /*--------------------------------------------------------------------*/
  1013.  
  1014.    xfer_stream = FOPEN( hostname, "r" , BINARY);
  1015.                               /* Open stream to transmit       */
  1016.    if (xfer_stream == NULL)
  1017.    {
  1018.       printmsg(0, "rsfile: Cannot open file %s (%s).", fname, hostname);
  1019.       printerr(hostname);
  1020.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  1021.          return XFER_LOST;       /* School is out, die            */
  1022.       else
  1023.          return XFER_FILEDONE;   /* Tell them to send next file   */
  1024.    } /* if */
  1025.  
  1026.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  1027.    {
  1028.       printmsg(0, "rsfile: Cannot unbuffer file %s (%s).", fname, hostname);
  1029.       pktsendstr("RN2");         /* Tell them we cannot handle it */
  1030.       printerr(hostname);
  1031.       fclose(xfer_stream);
  1032.       xfer_stream = NULL;
  1033.       return XFER_ABORT;
  1034.    } /* if */
  1035.  
  1036. /*--------------------------------------------------------------------*/
  1037. /*  We have the file open, announce it to the log and to the remote   */
  1038. /*--------------------------------------------------------------------*/
  1039.  
  1040.    if (!pktsendstr("RY"))
  1041.    {
  1042.       fclose(xfer_stream);
  1043.       xfer_stream = NULL;
  1044.       return XFER_LOST;
  1045.    }
  1046.  
  1047.    printmsg(0, "Sending \"%s\" (%s) as \"%s\"", fname, hostname, tname);
  1048.  
  1049.    return XFER_SENDDATA;   /* Switch to send data state        */
  1050.  
  1051. } /*rsfile*/
  1052.  
  1053. /*--------------------------------------------------------------------*/
  1054. /*    r d a t a                                                       */
  1055. /*                                                                    */
  1056. /*    Receive Data                                                    */
  1057. /*--------------------------------------------------------------------*/
  1058.  
  1059. XFER_STATE rdata( void )
  1060. {
  1061.    int    len;
  1062.    int    used = 0;
  1063.  
  1064.    do {
  1065.  
  1066.       if ((*getpkt)((char *) (databuf + used), &len) != OK)
  1067.       {
  1068.          fclose(xfer_stream);
  1069.          xfer_stream = NULL;
  1070.          return XFER_LOST;
  1071.       }
  1072.       else
  1073.          used += len;
  1074.  
  1075.    }  while (((used + pktsize) <= xfer_bufsize) && len);
  1076.  
  1077. /*--------------------------------------------------------------------*/
  1078. /*                  Write incoming data to the file                   */
  1079. /*--------------------------------------------------------------------*/
  1080.  
  1081.    if (used && (bufwrite((char *) databuf, used) < (int) used))
  1082.    {                                                        /* ahd   */
  1083.       printmsg(0, "rdata: Error writing data to file.");
  1084.       fclose(xfer_stream);
  1085.       xfer_stream = NULL;
  1086.       return XFER_ABORT;
  1087.    }
  1088.  
  1089. /*--------------------------------------------------------------------*/
  1090. /*                         Handle end of file                         */
  1091. /*--------------------------------------------------------------------*/
  1092.  
  1093.    if (len == 0)
  1094.       return XFER_RECVEOF;
  1095.    else
  1096.       return XFER_RECVDATA;      /* Remain in data state                */
  1097.  
  1098. } /*rdata*/
  1099.  
  1100. /*--------------------------------------------------------------------*/
  1101. /*    r e o f                                                         */
  1102. /*                                                                    */
  1103. /*    Process EOF for a received file                                 */
  1104. /*--------------------------------------------------------------------*/
  1105.  
  1106. XFER_STATE reof( void )
  1107. {
  1108.    struct tm *tmx;
  1109.    struct timeb now;
  1110.    long ticks;
  1111.    char *cy = "CY";
  1112.    char *cn = "CN";
  1113.    char *response = cy;
  1114.    char *fname = spool ? tempname : spolname;
  1115.  
  1116. /*--------------------------------------------------------------------*/
  1117. /*            Close out the file, checking for I/O errors             */
  1118. /*--------------------------------------------------------------------*/
  1119.  
  1120.    fclose(xfer_stream);
  1121.    if (ferror (xfer_stream ))
  1122.    {
  1123.       response = cn;          /* Report we had a problem             */
  1124.       printerr( fname );
  1125.    }
  1126.  
  1127.    xfer_stream = NULL;        /* To make sure!                       */
  1128.  
  1129. /*--------------------------------------------------------------------*/
  1130. /*    If it was a spool file, rename it to its permanent location     */
  1131. /*--------------------------------------------------------------------*/
  1132.  
  1133.    if (spool && equal(response,cy))
  1134.    {
  1135.       unlink( spolname );     /* Should be safe, since we only do it
  1136.                                  for spool files                     */
  1137.  
  1138.       if ( RENAME(tempname, spolname ))
  1139.       {
  1140.          printmsg(0,"reof: Unable to rename %s to %s",
  1141.                   tempname, spolname);
  1142.          response = cn;
  1143.          printerr(spolname);
  1144.       } /* if ( RENAME(tempname, spolname )) */
  1145.       spool = FALSE;
  1146.    } /* if (equal(response,cy) && spool) */
  1147.  
  1148.    if (!pktsendstr(response)) /* Announce we accepted the file       */
  1149.       return XFER_LOST;       /* No ACK?  Return, if so              */
  1150.  
  1151.    if ( !equal(response, cy) )   /* If we had an error, delete file  */
  1152.    {
  1153.       printmsg(0,"reof: Deleting corrupted file %s", fname );
  1154.       unlink(fname );
  1155.       return XFER_ABORT;
  1156.    } /* if ( !equal(response, cy) ) */
  1157.  
  1158. /*--------------------------------------------------------------------*/
  1159. /*            The file is delivered; compute stats for it             */
  1160. /*--------------------------------------------------------------------*/
  1161.  
  1162.    remote_stats.freceived++;
  1163.    remote_stats.breceived += bytes;
  1164.  
  1165.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  1166.    {
  1167.       ftime(&now);
  1168.       ticks = (now.time - start_time.time) * 1000 +
  1169.                ((long) now.millitm - (long) start_time.millitm);
  1170.       printmsg(2, "Transfer completed, %ld chars/sec",
  1171.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  1172.  
  1173.       if ( bflag[F_SYSLOG] )
  1174.       {
  1175.          tmx = localtime(&now.time);
  1176.          if ( bflag[F_MULTITASK] )
  1177.             syslog = FOPEN(SYSLOG, "a", TEXT);
  1178.  
  1179.          if (( syslog == NULL ) || setvbuf( syslog, NULL, _IONBF, 0))
  1180.             printerr(SYSLOG);
  1181.          else {
  1182.             fprintf( syslog,
  1183.                "%s!%s (%s) (%d/%d-%02d:%02d:%02d) <- %ld / %ld.%02d secs\n",
  1184.                    rmtname, tname, spolname,
  1185.                    (tmx->tm_mon+1), tmx->tm_mday,
  1186.                    tmx->tm_hour, tmx->tm_min, tmx->tm_sec, bytes,
  1187.                    ticks / 1000 , (int) ((ticks % 1000) / 10) );
  1188.             fclose( syslog );
  1189.             syslog = NULL;
  1190.          }
  1191.  
  1192.       } /* if ( bflag[SYSLOG ) */
  1193.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  1194.  
  1195. /*--------------------------------------------------------------------*/
  1196. /*                      Return success to caller                      */
  1197. /*--------------------------------------------------------------------*/
  1198.  
  1199.    return XFER_FILEDONE;
  1200. } /* reof */
  1201.  
  1202. /*--------------------------------------------------------------------*/
  1203. /*                           MISC ROUTINES                            */
  1204. /*--------------------------------------------------------------------*/
  1205.  
  1206. /*--------------------------------------------------------------------*/
  1207. /*    p k t s e n d s t r                                             */
  1208. /*                                                                    */
  1209. /*    Transmit a control packet                                       */
  1210. /*--------------------------------------------------------------------*/
  1211.  
  1212. static boolean pktsendstr( char *s )
  1213. {
  1214.  
  1215.    printmsg(2, ">>> %s", s);
  1216.  
  1217. /*--------------------------------------------------------------------*/
  1218. /*    We flush here because we know we're in control and not          */
  1219. /*    waiting for remote data we could miss.                          */
  1220. /*--------------------------------------------------------------------*/
  1221.  
  1222.    if ( (! bflag[ F_MULTITASK ]) || (debuglevel > 2) )
  1223.       fflush( logfile );         /* Known safe place  to flush log      */
  1224.  
  1225.    if((*wrmsg)(s) != OK )
  1226.       return FALSE;
  1227.  
  1228.    remote_stats.bsent += strlen(s)+1;
  1229.  
  1230.    return TRUE;
  1231. } /* pktsendstr */
  1232.  
  1233. /*--------------------------------------------------------------------*/
  1234. /*    p k t g e t s t r                                               */
  1235. /*                                                                    */
  1236. /*    Receive a control packet                                        */
  1237. /*--------------------------------------------------------------------*/
  1238.  
  1239. static boolean pktgetstr( char *s)
  1240. {
  1241.    if ((*rdmsg)(s) != OK )
  1242.      return FALSE;
  1243.  
  1244.    remote_stats.breceived += strlen( s ) + 1;
  1245.    printmsg(2, "<<< %s", s);
  1246.  
  1247.    return TRUE;
  1248. } /* pktgetstr */
  1249.  
  1250. /*--------------------------------------------------------------------*/
  1251. /*    b u f _ i n i t                                                 */
  1252. /*                                                                    */
  1253. /*    Alocate buffers for file transfer                               */
  1254. /*--------------------------------------------------------------------*/
  1255.  
  1256. static void buf_init( void )
  1257. {
  1258.    xfer_bufsize = max( pktsize * 4, max( M_xfer_bufsize, BUFSIZ) );
  1259.  
  1260.    if (databuf == NULL)
  1261.       databuf = malloc( xfer_bufsize );
  1262.    else
  1263.       databuf = realloc( databuf, xfer_bufsize );
  1264.    checkref( databuf );
  1265.  
  1266. } /* buf_init */
  1267.